package com.baymax.test.scene.demo

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.animation.TypeEvaluator
import android.animation.ValueAnimator
import android.graphics.Color
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.util.Log
import android.view.*
import android.view.animation.OvershootInterpolator
import android.widget.FrameLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.animation.addListener
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.animation.PathInterpolatorCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ItemDecoration
import com.baymax.test.scene.BaseScene
import com.baymax.test.scene.R
import com.baymax.test.scene.addButton
import com.baymax.test.scene.addDFView
import com.baymax.test.scene.internal.ViewWrapper
import com.baymax.test.scene.newSceneFlexContainer
import com.baymax.test.scene.view.HighLightWrapper
import com.baymax.test.scene.view.RippleView
import com.bytedance.scene.ktx.navigationScene
import com.bytedance.scene.navigation.OnBackPressedListener
import kotlin.random.Random

/**
 * @title:       标题
 * @project:     TestScene
 * @package:     com.baymax.test.scene.demo
 * @class:       DrawOrderScene
 * @description:
 * <p>
 * 类描述
 * </p>
 *
 * @version:   1.0
 * @createDate:   2022/11/29 16:02
 * @Copyright (C) 2022 YSTEN
 * @author:       xuyujian
 */
class AnimatorScene : BaseScene() {
    override fun onCreateView(p0: LayoutInflater, p1: ViewGroup, p2: Bundle?): View =
        p1.newSceneFlexContainer {

            val scene = this@AnimatorScene

            val c = p1.context
            val rv = RecyclerView(c)
            rv.clipToPadding = false
            rv.clipChildren = false
            rv.setPadding(80, 30, 80, 30)
            val manager = object : LinearLayoutManager(requireActivity()) {

                override fun layoutDecoratedWithMargins(
                    child: View,
                    left: Int,
                    top: Int,
                    right: Int,
                    bottom: Int
                ) {
                    super.layoutDecoratedWithMargins(child, left, top, right, bottom)
                    println("$child :: $left -- ${child.x}")
                }

            }.apply {
                orientation = LinearLayoutManager.HORIZONTAL
            }
            rv.layoutManager = manager
            var scaleIndex = 0
            addButton("scale next : $scaleIndex") {
                val old = scaleIndex
                scaleIndex = scaleIndex.plus(1).mod(12)
                rv.adapter?.notifyItemChanged(scaleIndex, "max")
                if (old != scaleIndex) {
                    rv.adapter?.notifyItemChanged(old, "min")
                }
                this.text = "scale next : $scaleIndex"

            }
            rv.background = GradientDrawable().apply {
                setStroke(2, Color.GREEN)
            }
            rv.addItemDecoration(object : ItemDecoration() {
                override fun getItemOffsets(
                    outRect: Rect,
                    itemPosition: Int,
                    parent: RecyclerView
                ) {
                    return outRect.set(6, 6, 6, 6)
                }
            })
            addView(rv)
            class VH(itemView: View) : RecyclerView.ViewHolder(itemView) {
                val txt = itemView as TextView

                init {
                    txt.apply {
                        minHeight = 80
                        minWidth = 80
                        textSize = 20f
                        gravity = Gravity.CENTER
                        setTextColor(Color.RED)
                        setBackgroundColor(Color.YELLOW)
                        isFocusable = true
                        setOnFocusChangeListener { v, hasFocus ->
                            if (hasFocus) {
                                rv.postInvalidate()
                                v.setBackgroundColor(Color.BLUE)

                            } else {
                                setBackgroundColor(Color.YELLOW)
                            }
                            if (scaleIndex == this@VH.adapterPosition) {
                                rv.adapter?.notifyItemChanged(scaleIndex, "max")
                            }

                        }
                    }
                }
            }

            rv.adapter = object : RecyclerView.Adapter<VH>() {
                override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH =
                    VH(TextView(c))


                override fun onBindViewHolder(holder: VH, position: Int) {
                    holder.txt.text = "P:$position"

                }

                override fun onBindViewHolder(
                    holder: VH,
                    position: Int,
                    payloads: MutableList<Any>
                ) {
                    super.onBindViewHolder(holder, position, payloads)
                    println("payloads $payloads")
                    payloads.forEach {
                        when (it) {
                            "request" -> holder.itemView.requestFocus()
                            "max" -> ObjectAnimator.ofInt(
                                ViewWrapper(holder.itemView),


                                "width",
                                holder.itemView.width,
                                160
                            )
                                .setDuration(600)
                                .start()

                            "min" -> ObjectAnimator.ofInt(
                                ViewWrapper(holder.itemView),
                                "width",
                                holder.itemView.width,
                                80
                            )
                                .setDuration(600)
                                .start()

                            else -> println("payloads none op $it")
                        }
                    }
                }

                override fun getItemViewType(position: Int) = 1
                override fun getItemCount(): Int = 12
            }.also {
                it.notifyDataSetChanged()
                //rv.post { it.notifyItemChanged(3, "request") }
            }

            val gradientDrawable = GradientDrawable()
            gradientDrawable.setStroke(10, Color.RED)
            gradientDrawable.setColor(Color.GREEN)
            gradientDrawable.cornerRadius = 10f
            gradientDrawable.mutate()
            val frame = FrameLayout(context)
            val v = View(context)
            frame.translationX = 100f
            v.background = gradientDrawable
            frame.addView(v, 100, 100)
            addView(frame, 200, 200)
            frame.background = GradientDrawable().apply {
                setStroke(2, Color.CYAN)
            }
            v.post {
                println("gradientDrawable $gradientDrawable")
                println("gradientDrawable ${gradientDrawable.bounds}")

            }
            val b = BackGroundTypeEvaluator(gradientDrawable, Color.GREEN, Color.RED, 10)
            var show = b.currentAlpha >= 1
            addButton("test animate backGround with path Interpolator") {
                val animator = if (show) {
                    ValueAnimator.ofObject(b, b.currentAlpha, 1)
                } else {
                    ValueAnimator.ofObject(b, b.currentAlpha, 0)
                }
                animator.interpolator = PathInterpolatorCompat.create(0.42f, 0f, 0.58f, 1f)
                animator.duration = 800
                animator.start()
                show = !show
            }
            addButton("test animate backGround") {
                val animator = if (show) {
                    ValueAnimator.ofObject(b, b.currentAlpha, 1)
                } else {
                    ValueAnimator.ofObject(b, b.currentAlpha, 0)
                }
                animator.duration = 800
                animator.start()
                show = !show
            }

            val breathAnimator = {
                ValueAnimator.ofObject(b, 1f, 0.4f, 1f).also { animator ->
                    animator.setDuration(3000)
                    animator.addListener(
                        onStart = { println("animator onStart") },
                        onEnd = { println("animator onEnd") }
                    )
                }
            }
            val setAnimator = { creators: () -> Array<Animator> ->
                AnimatorSet().also { a ->
                    a.playSequentially(*creators())
                    a.addListener(
                        onStart = {
                            println("set onStart")
                        },
                        onEnd = {
                            a.start()
                        }
                    )

                }
            }
            addButton("breath") {
                breathAnimator().start()
            }
            addButton("breath") {
                breathAnimator().start()
            }
            addButton("repeat and first delay") {
                var count = if (show) 1 else 0
                val set = AnimatorSet()
                val delay = ValueAnimator.ofFloat(0f, 1f);
                delay.setDuration(0)
                set.playSequentially(delay, breathAnimator())
                set.addListener(
                    onStart = {
                        println("set onStart")
                    },
                    onEnd = {
                        delay.setDuration(if (count > 0) 2000 else 0)
                        println("set onEnd")
                        count++
                        set.start()
                    }
                )
                set.start()
                show = !show

                addButton("cancel") {
                    set.cancel()
                }

            }
            addButton("overshoot") {
                val vf = if (v.isSelected) 1f else 1.3f
                v.animate().scaleX(vf).scaleY(vf)
                    .setInterpolator(OvershootInterpolator(2f))
                    .setDuration(600)
                    .withEndAction {

                        v.isSelected = v.scaleX != 1f
                    }.start()

            }

            addButton("highLight") {

                val high = HighLightWrapper(context)
                val content = requireActivity().findViewById<ViewGroup>(android.R.id.content)
                content.addView(
                    high,
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )

                val back = object : OnBackPressedListener {
                    override fun onBackPressed(): Boolean {
                        scene.navigationScene?.removeOnBackPressedListener(this)
                        return (content.parent != null).apply {
                            (high.parent as? ViewGroup)?.removeView(high)
                        }

                    }
                }
                scene.navigationScene?.addOnBackPressedListener(scene, back)

                val rect = RectF(
                    frame.left.toFloat() + frame.translationX,
                    frame.top.toFloat(),
                    frame.right.toFloat() + frame.translationX,
                    frame.bottom.toFloat()
                )
                high.setBounds(rect)


                content.postDelayed({
                    val start: RectF = RectF(high.f)
                    val end = RectF(start)
                    val hitRect: RectF = RectF()
                    end[end.left, end.top, end.right + 100] = end.bottom
                    val rectFEvaluator = HighLightWrapper.RectFEvaluator(hitRect)
                    val propertyValuesHolder = PropertyValuesHolder.ofObject(
                        high.property,
                        rectFEvaluator,
                        start,
                        end
                    )
                    val valueAnimator =
                        ObjectAnimator.ofPropertyValuesHolder(high, propertyValuesHolder)
                    valueAnimator.duration = 800
                    valueAnimator.start()
                }, 2000)

            }
            val t = AppCompatTextView(context)
            t.text = "hello"
            addView(t)
            t.translationX = 100f
            t.setBackgroundResource(R.mipmap.setting)
            val r = Random(System.currentTimeMillis())
            addButton("tint") {
                val rc = Color.rgb(r.nextInt(256), r.nextInt(256), r.nextInt(256))

                t.setCompoundDrawables(
                    DrawableCompat.wrap(resources.getDrawable(R.mipmap.setting)).apply {
                        DrawableCompat.setTint(this, rc)
                        this.setBounds(0, 0, 40, 40)
                    }, null, null, null
                )

            }

            val rippleView = addDFView(200, 200, RippleView(context)) {

            }
            addButton("ripple") {
                rippleView.startRippleAnimation()
            }

        }


    class BackGroundTypeEvaluator(
        private val drawable: GradientDrawable,
        private val solidColor: Int,
        private val borderColor: Int,
        private val borderWidth: Int,
    ) : TypeEvaluator<Float> {

        init {
            drawable.mutate()
        }

        val rect = android.animation.RectEvaluator()


        var currentAlpha = 1f

        override fun evaluate(fraction: Float, startValue: Float, endValue: Float): Float {
            val alpha = startValue + fraction * (endValue - startValue)
            val solid = com.facebook.drawee.drawable.DrawableUtils.multiplyColorAlpha(
                solidColor,
                ((255 * alpha).toInt())
            )
            val border = com.facebook.drawee.drawable.DrawableUtils.multiplyColorAlpha(
                borderColor,
                ((255 * alpha).toInt())
            )
            println("fraction $fraction v：$alpha , color ${solid.toString(16)} ,${border.toString(16)}")
            drawable.setStroke(borderWidth, border)
            drawable.setColor(solid)
            this.currentAlpha = alpha
            if (fraction == 0f) {
                val r = drawable.bounds
                Log.d(TAG, "updateAnimateDrawableState ${r}")
                // drawable.updateBounds(r.left, r.top, r.right, 80)
            }

            return alpha
        }
    }

}